home *** CD-ROM | disk | FTP | other *** search
- /**************************************************************
- *
- * ACS_PLUS.C
- *
- **************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h> /* because of ltoa(), ... */
- #include <tos.h> /* because of Fforce(), ... */
- #include <acs.h>
- #include <acs_plus.pif>
- #include "acs_plus.h"
- #include "acs_plus.ah"
- #include <messages.pif>
-
-
- /**************************************************************
- *
- * memory management
- *
- **************************************************************/
-
- /*** global variable, used to point to symptom data for debug_mem ***/
-
- char *memory_symptom ;
-
-
- /*** global variable for recording memory management operations ***/
-
- #define MAX_OPERATIONS 64
-
- struct OPERATION
- {
- enum {Memory, String, Object, Window} type ;
- long ptr ;
- long size ;
- } ;
-
- static struct OPERATION operation[MAX_OPERATIONS] ;
- static char i = 0 ;
-
- /*** own memory management ***/
-
- #define BLOCK_SIZE 0x10000L /* size to be allocated in 1 one block */
- #define MIN_BYTES 4 /* minimum length of last section */
-
- struct BH /* block header for blocks of allocated memory */
- { /* sizeof(BH) must be a multiple of 4 */
- long size ; /* total size of block */
- long free ; /* net free size */
- struct BH *next ; /* pointer to next list element */
- long cs ; /* checksum for this header */
- }
- *bh_first = NULL ; /* pointer to first list element */ ;
-
- struct SH /* section header for memory sections inside blocks */
- { /* sizeof(SH) must be a multiple of 4 */
- long size ; /* net size of following section */
- int FREE ; /* TRUE = next section is free */
- int cs ; /* checksum for this header */
- } ;
-
-
-
- long block_cs(struct BH *bh)
- { return ~( bh->size + bh->free + (long)(bh->next) ) ; }
-
- int section_cs(struct SH *sh)
- { return ~( (int)sh->size + sh->FREE ) ; }
-
-
- void *new_block(long blocksize, long size)
- {
- struct BH *bh ;
- struct SH *sh, *sh_next ;
-
- /*** allocate memory ***/
- bh = (struct BH *)Ax_malloc(blocksize) ;
- if (bh == NULL) { alert_str(OUT_OF_MEMORY, "") ; return NULL ; }
-
- /*** init headers ***/
- bh->next = bh_first ; bh_first = bh ; /* chain in */
- bh->size = blocksize ;
- sh = (struct SH *)(bh + 1) ;
- sh->FREE = FALSE ;
-
- /*** init 1 header for free section ***/
- sh->size = blocksize - sizeof(*bh) - sizeof(*sh) ;
- bh->free = 0 ;
- if (size + sizeof(*bh) + (sizeof(*sh)<<1) + MIN_BYTES <= blocksize)
- {
- /*** init 1 more header for free section ***/
- sh->size = size ;
- sh_next = (struct SH *)((long)(sh + 1) + sh->size) ;
- sh_next->FREE = TRUE ;
- sh_next->size = blocksize - size - sizeof(*bh) - (sizeof(*sh)<<1) ;
- sh_next->cs = section_cs(sh_next) ;
- bh->free = sh_next->size ;
- }
- sh->cs = section_cs(sh) ;
- bh->cs = block_cs(bh) ;
-
- /*** return pointer to user section ***/
- return (void *)(sh + 1) ;
- }
-
-
- void *Allocate(long size)
- {
- struct SH *sh, *sh_new ;
- struct BH *bh ;
- char address[30] ;
-
- /*** round up size to a multiple of 4 ***/
- size = (size + 3) & 0xfffffffcL ;
-
- /*** if requested size is big enough, user gets an extra block ***/
- if (size > BLOCK_SIZE / 2) return new_block(size + sizeof(*bh) + sizeof(*sh), size) ;
-
- /*** else: search for a free section inside allocated blocks ***/
- bh = bh_first ;
- while (bh != NULL)
- {
- if (bh->cs != block_cs(bh))
- {
- alert_str(BLOCK_DESTROYED, ltoa((long)bh, address, 16)) ;
- return NULL ;
- }
- if (bh->free >= size)
- {
- /*** search this block for a free section ***/
- sh = (struct SH *)(bh + 1) ;
- while ( (long)sh < (long)bh + bh->size )
- {
- if (sh->cs != section_cs(sh))
- {
- alert_str(SECTION_DESTROYED, ltoa((long)sh, address, 16)) ;
- return NULL ;
- }
- if (sh->FREE)
- {
- if (sh->size >= size)
- {
- /*** allocate section (partly) ***/
- if (sh->size >= size + sizeof(*sh) + MIN_BYTES )
- {
- /*** create new section header ***/
- sh_new = (struct SH *)((long)(sh + 1) + size) ;
- sh_new->FREE = TRUE ;
- sh_new->size = sh->size - size - sizeof(*sh_new) ;
- sh_new->cs = section_cs(sh_new) ;
-
- /*** update block header ***/
- bh->free -= sizeof(*sh_new) ;
-
- /*** update section header ***/
- sh->size = size ;
- }
- sh->FREE = FALSE ;
- sh->cs = section_cs(sh) ;
- bh->free -= sh->size ;
- bh->cs = block_cs(bh) ;
- return (void *)(sh + 1) ;
- }
- } /* if section is free */
- sh = (struct SH *)( (long)(sh + 1) + sh->size ) ;
- }
- } /* if enough free memory in this block */
- bh = bh->next ;
- }
- /*** nothing suitable found up to now -> allocate new block ***/
- return new_block(BLOCK_SIZE, size) ;
- }
-
-
- void Free(void *ptr)
- {
- struct BH *bh_prev, *bh ;
- struct SH *sh, *sh_next, *sh_prev ;
- char address[30] ;
-
- bh_prev = NULL ;
- bh = bh_first ;
- while (bh != NULL)
- {
- if (bh->cs != block_cs(bh))
- {
- alert_str(BLOCK_DESTROYED, ltoa((long)bh, address, 16)) ;
- return ;
- }
- if ( ((long)ptr >= (long)bh + sizeof(*bh) + sizeof(*sh))
- && ((long)ptr < (long)bh + bh->size) )
- {
- /*** memory to be freed lies in this block ***/
- sh = (struct SH *)(bh + 1) ; sh_prev = sh ;
- while ( (long)sh < (long)bh + bh->size )
- {
- if (sh->cs != section_cs(sh))
- {
- alert_str(SECTION_DESTROYED, ltoa((long)sh, address, 16)) ;
- return ;
- }
- if ((void *)(sh + 1) == ptr)
- {
- /*** free section ***/
- sh->FREE = TRUE ;
- bh->free += sh->size ;
- sh_next = (struct SH *)((long)(sh + 1) + sh->size) ;
- if ((long)sh_next + sizeof(*sh_next) + MIN_BYTES <= (long)bh + bh->size )
- {
- if (sh_next->cs != section_cs(sh_next))
- {
- alert_str(SECTION_DESTROYED, ltoa((long)sh, address, 16)) ;
- return ;
- }
- if (sh_next->FREE)
- {
- /*** put together both free sections ***/
- sh->size += (sizeof(*sh_next) + sh_next->size) ;
-
- /*** update block header ***/
- bh->free += sizeof(*sh_next) ;
- }
- }
- sh->cs = section_cs(sh) ;
- if ((sh_prev->FREE) && (sh_prev != sh))
- {
- /*** put together both free sections ***/
- sh_prev->size += (sizeof(*sh) + sh->size) ;
- sh_prev->cs = section_cs(sh_prev) ;
-
- /*** update block header ***/
- bh->free += sizeof(*sh) ;
- }
- bh->cs = block_cs(bh) ;
- if (bh->free + sizeof(*bh) + sizeof(*sh) == bh->size)
- {
- /*** block is empty, it can be freed ***/
- if (bh_prev == NULL) bh_first = bh->next ;
- else
- {
- bh_prev->next = bh->next ;
- bh_prev->cs = block_cs(bh_prev) ;
- }
- Ax_free(bh) ;
- }
- return ;
- }
- sh_prev = sh ;
- sh = (struct SH *)( (long)(sh + 1) + sh->size ) ;
- }
- } /* if inside this block */
- bh_prev = bh ;
- bh = bh->next ;
- }
- alert_str(NOT_ALLOCATED, "") ;
- }
-
-
- void debug_mem (void* defective)
- {
- char all_symptoms[30] = "" ;
-
- ltoa( (long)defective, all_symptoms, 0x10) ;
- strncat(all_symptoms, " ", 1) ;
- strncat(all_symptoms, memory_symptom, 20) ;
- alert_str(MEMORY_ERROR, all_symptoms) ;
- }
-
-
- void *My_shrink(void *memory, long size)
- {
- void *new_memory ;
-
- /*** free memory if new size shall be 0 ***/
- if (!size)
- {
- My_free(memory) ;
- return NULL ;
- }
- /*** allocate new memory ***/
- new_memory = My_alloc(size) ;
- if (!new_memory) return memory ; /* not "shrinked" */
-
- /*** copy old to new ***/
- memcpy(new_memory, memory, size) ;
-
- /*** free old memory ***/
- My_free(memory) ;
-
- /*** return pointer to new memory ***/
- return new_memory ;
- }
-
-
- void *My_alloc(long size)
- {
- void *ptr = Allocate(size) ;
- if (i < MAX_OPERATIONS)
- {
- operation[i].type = Memory ;
- operation[i].ptr = (long)ptr ;
- operation[i].size = size ;
- i++ ;
- }
- return ptr ;
- }
-
- void My_free(void *ptr)
- {
- Free(ptr) ;
- if (i < MAX_OPERATIONS)
- {
- operation[i].type = Memory ;
- operation[i].ptr = (long)ptr ;
- operation[i].size = 0 ;
- i++ ;
- }
- }
-
-
- char *Myst_create(const char *parent)
- {
- char *ptr = Ast_create(parent) ;
- if (i < MAX_OPERATIONS)
- {
- operation[i].type = String ;
- operation[i].ptr = (long)ptr ;
- operation[i].size = strlen(parent) ;
- i++ ;
- }
- return ptr ;
- }
-
- void Myst_delete(char *ptr)
- {
- Ast_delete(ptr) ;
- if (i < MAX_OPERATIONS)
- {
- operation[i].type = String ;
- operation[i].ptr = (long)ptr ;
- operation[i].size = 0 ;
- i++ ;
- }
- }
-
-
- OBJECT *Myob_create(const OBJECT *parent)
- {
- OBJECT *ptr = Aob_create(parent) ;
- if (i < MAX_OPERATIONS)
- {
- operation[i].type = Object ;
- operation[i].ptr = (long)ptr ;
- operation[i].size = sizeof(*ptr) ;
- i++ ;
- }
- return ptr ;
- }
-
- void Myob_delete(OBJECT *ptr)
- {
- Aob_delete(ptr) ;
- if (i < MAX_OPERATIONS)
- {
- operation[i].type = Object ;
- operation[i].ptr = (long)ptr ;
- operation[i].size = 0 ;
- i++ ;
- }
- }
-
-
- Awindow *Mywi_create(const Awindow *parent)
- {
- Awindow *ptr = Awi_create(parent) ;
- if (i < MAX_OPERATIONS)
- {
- operation[i].type = Window ;
- operation[i].ptr = (long)ptr ;
- operation[i].size = sizeof(*ptr) ;
- i++ ;
- }
- return ptr ;
- }
-
- void Mywi_delete(Awindow *ptr)
- {
- Awi_delete(ptr) ;
- if (i < MAX_OPERATIONS)
- {
- operation[i].type = Window ;
- operation[i].ptr = (long)ptr ;
- operation[i].size = 0 ;
- i++ ;
- }
- }
-
-
- void print_operations(void)
- {
- Fforce(1, (int)Fdup(3)) ;
- for (i = 0 ; i < MAX_OPERATIONS ; i++)
- {
- switch (operation[i].type)
- {
- case Memory: printf("Memory %lx", (long)operation[i].ptr) ; break ;
- case String: printf("String %lx", (long)operation[i].ptr) ; break ;
- case Object: printf("Object %lx", (long)operation[i].ptr) ; break ;
- case Window: printf("Window %lx", (long)operation[i].ptr) ; break ;
- }
- printf(" Size %lx \n", operation[i].size) ;
- }
- Fforce(1, (int)Fdup(1)) ;
- }
-
-
- /**************************************************************
- *
- * timer management
- *
- **************************************************************/
-
- static Awindow *waiting_wi = NULL ;
- static int rest_time ;
-
- int set_timer(Awindow *wi)
- {
- if ((!waiting_wi) || (wi == waiting_wi))
- {
- rest_time = 3000 ; /* ms */
- waiting_wi = wi ; /* now timer is running */
- return 0 ;
- }
- else return -1 ;
- }
-
- void stop_timer(Awindow *wi)
- { waiting_wi = NULL ; }
-
- static void timer(void)
- {
- Awindow *buffer_wi ;
-
- if (waiting_wi)
- {
- /*** a job is running */
- rest_time -= ev_mtcount ;
- if (rest_time <= 0)
- {
- /*** timer expired ***/
- buffer_wi = waiting_wi ;
- waiting_wi = NULL ; /* timer is stopped now */
- Awi_sendall(REDRAW, buffer_wi) ;
- }
- }
- }
-
- void init_time(void)
- { ACSblk->ACStimer = timer ; /* replace with own timer procedure */ }
-
-
-
-